#include "isp.h"

#include <pthread.h>
#include <stdio.h>

#include "hi_sns_ctrl.h"
#include "mpi_isp.h"
#include "mpi_ae.h"
#include "mpi_awb.h"

HI_VOID *ISP_Thread(HI_VOID *pArgs)
{
    HI_S32 s32Ret;

    ISP_DEV IspDev = (ISP_DEV)(HI_UINTPTR_T)pArgs;

    s32Ret = HI_MPI_ISP_Run(IspDev);
    if (HI_SUCCESS != s32Ret)
    {
        printf("[FAIL] HI_MPI_ISP_Run: %x\n", s32Ret);
    }

    return HI_NULL;
}

HI_S32 ISP_Init(VI_PIPE ViPipe)
{
    HI_S32 s32Ret;

    ISP_DEV IspDev = ViPipe;
    const ISP_SNS_OBJ_S *pstSnsObj = &stSnsImx335Obj;

    ALG_LIB_S stAeLib;
    ALG_LIB_S stAwbLib;
    stAeLib.s32Id = IspDev;
    stAwbLib.s32Id = IspDev;
    strncpy_s(stAeLib.acLibName, sizeof(HI_AE_LIB_NAME) + 1, HI_AE_LIB_NAME, sizeof(HI_AE_LIB_NAME));
    strncpy_s(stAwbLib.acLibName, sizeof(HI_AWB_LIB_NAME) + 1, HI_AWB_LIB_NAME, sizeof(HI_AWB_LIB_NAME));

    if (HI_NULL != pstSnsObj->pfnRegisterCallback)
    {
        s32Ret = pstSnsObj->pfnRegisterCallback(IspDev, &stAeLib, &stAwbLib);
        if (HI_SUCCESS != s32Ret)
        {
            printf("[FAIL] pstSnsObj->pfnRegisterCallback: %x\n", s32Ret);
            return HI_FAILURE;
        }
    }
    else
    {
        printf("[FAIL] pstSnsObj->pfnRegisterCallback is NULL\n");
        return HI_FAILURE;
    }

    ISP_SNS_COMMBUS_U uSnsBusInfo;
    uSnsBusInfo.s8I2cDev = 0;

    if (HI_NULL != pstSnsObj->pfnSetBusInfo)
    {
        s32Ret = pstSnsObj->pfnSetBusInfo(IspDev, uSnsBusInfo);
        if (HI_SUCCESS != s32Ret)
        {
            printf("[FAIL] pstSnsObj->pfnSetBusInfo: %x\n", s32Ret);
            return HI_FAILURE;
        }
    }
    else
    {
        printf("[FAIL] pstSnsObj->pfnSetBusInfo is NULL!\n");
        return HI_FAILURE;
    }

    s32Ret = HI_MPI_AE_Register(IspDev, &stAeLib);
    if (HI_SUCCESS != s32Ret)
    {
        printf("[FAIL] HI_MPI_AE_Register: %x\n", s32Ret);
        return HI_FAILURE;
    }

    s32Ret = HI_MPI_AWB_Register(IspDev, &stAwbLib);
    if (HI_SUCCESS != s32Ret)
    {
        printf("[FAIL] HI_MPI_AWB_Register: %x\n", s32Ret);
        return HI_FAILURE;
    }

    s32Ret = HI_MPI_ISP_MemInit(ViPipe);
    if (HI_SUCCESS != s32Ret)
    {
        printf("[FAIL] HI_MPI_ISP_MemInit: %x\n", s32Ret);
        return HI_FAILURE;
    }

    ISP_PUB_ATTR_S stPubAttr =
        {
            .stWndRect =
                {
                    .s32X = 0,
                    .s32Y = 0,
                    .u32Width = 2592,
                    .u32Height = 1536,
                },
            .stSnsSize =
                {
                    .u32Width = 2592,
                    .u32Height = 1944,
                },
            .f32FrameRate = 30,
            .enBayer = BAYER_RGGB,
            .enWDRMode = WDR_MODE_NONE,
            .u8SnsMode = 0,
        };

    s32Ret = HI_MPI_ISP_SetPubAttr(ViPipe, &stPubAttr);
    if (HI_SUCCESS != s32Ret)
    {
        printf("[FAIL] HI_MPI_ISP_SetPubAttr: %x\n", s32Ret);
        return HI_FAILURE;
    }

    ISP_CTRL_PARAM_S stIspCtrlParam;
    s32Ret = HI_MPI_ISP_GetCtrlParam(ViPipe, &stIspCtrlParam);
    if (HI_SUCCESS != s32Ret)
    {
        printf("[FAIL] HI_MPI_ISP_GetCtrlParam: %x\n", s32Ret);
        return HI_FAILURE;
    }

    stIspCtrlParam.u32StatIntvl = 30 / 30;
    s32Ret = HI_MPI_ISP_SetCtrlParam(ViPipe, &stIspCtrlParam);
    if (HI_SUCCESS != s32Ret)
    {
        printf("[FAIL] HI_MPI_ISP_SetCtrlParam: %x\n", s32Ret);
        return HI_FAILURE;
    }

    s32Ret = HI_MPI_ISP_Init(ViPipe);
    if (HI_SUCCESS != s32Ret)
    {
        printf("[FAIL] HI_MPI_ISP_Init: %x\n", s32Ret);
        return HI_FAILURE;
    }

    pthread_attr_t *pstAttr = HI_NULL;

    s32Ret = pthread_create(&s_hIspThread, pstAttr, ISP_Thread, (HI_VOID *)(HI_UINTPTR_T)IspDev);
    if (HI_SUCCESS != s32Ret)
    {
        printf("[FAIL] isp pthread_create: %x\n", s32Ret);
        return HI_FAILURE;
    }
    
    if (HI_NULL != pstAttr)
    {
        pthread_attr_destroy(pstAttr);
    }

    return HI_SUCCESS;
}

HI_VOID ISP_DeInit(ISP_DEV IspDev)
{
    HI_S32 s32Ret;

    if (s_hIspThread)
    {
        HI_MPI_ISP_Exit(IspDev);
        pthread_join(s_hIspThread, NULL);

        ALG_LIB_S stAwbLib;
        stAwbLib.s32Id = IspDev;
        strncpy_s(stAwbLib.acLibName, sizeof(HI_AWB_LIB_NAME) + 1, HI_AWB_LIB_NAME, sizeof(HI_AWB_LIB_NAME));
        s32Ret = HI_MPI_AWB_UnRegister(IspDev, &stAwbLib);
        if (HI_SUCCESS != s32Ret)
        {
            printf("[FAIL] HI_MPI_AWB_UnRegister: %x\n", s32Ret);
        }

        ALG_LIB_S stAeLib;
        stAeLib.s32Id = IspDev;
        strncpy_s(stAeLib.acLibName, sizeof(HI_AE_LIB_NAME) + 1, HI_AE_LIB_NAME, sizeof(HI_AE_LIB_NAME));        s32Ret = HI_MPI_AE_UnRegister(IspDev, &stAeLib);
        if (HI_SUCCESS != s32Ret)
        {
            printf("[FAIL] HI_MPI_AE_UnRegister: %x\n", s32Ret);
        }

        const ISP_SNS_OBJ_S *pstSnsObj = &stSnsImx335Obj;
        if (NULL != pstSnsObj->pfnUnRegisterCallback)
        {
            s32Ret = pstSnsObj->pfnUnRegisterCallback(IspDev, &stAeLib, &stAwbLib);
            if (HI_SUCCESS != s32Ret)
            {
                printf("[FAIL] pstSnsObj->pfnUnRegisterCallback: %x\n", s32Ret);
                return;
            }
        }
        else
        {
            printf("[FAIL] pstSnsObj->pfnUnRegisterCallback is NULL!\n");
        }
        s_hIspThread = 0;
    }
}